home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 May: Tool Chest / Dev.CD May 98 TC.toast / Tool Chest / Development Kits / HyperCard Related / APDA HyperCard Toolkits / CD Audio Toolkit 1.0 / Source / CDOpen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-07  |  9.8 KB  |  385 lines  |  [TEXT/MPS ]

  1. /*
  2.     CDOpen - An XCMD to open the .AppleCD driver for use by HyperCard.
  3.     ©Apple Computer, Inc. 1988
  4.     All Rights Reserved.
  5.     
  6.     88/10/08    BL°B    First Version
  7.  
  8.     To compile and link this file using Macintosh Programmer's Workshop,
  9.  
  10.     C -q2 CDOpen.c
  11.     link -sn Main=CDOpen -sn STDIO=CDOpen ∂
  12.          -sn INTENV=CDOpen -rt XFCN=42 ∂
  13.          -m CDOpen CDOpen.c.o "{CLibraries}"CRuntime.o ∂
  14.          "{CLibraries}"CInterface.o ∂
  15.          -o HyperCommands
  16.          
  17.     This link directive puts the XCMD in the file "HyperCommands".
  18.     Substitute the name of the stack you want it in.  To move XCMDs
  19.     between stacks, use ResEdit.  They can be in an individual stack,
  20.     the Home stack, the HyperCard application, or the System File.
  21.     
  22. */
  23.  
  24. #include <cd.h>
  25. #include <SysEqu.h>
  26. #include <strings.h>
  27.  
  28. #define dRAMBased    0x40    /* bit 6 -- see IM II-190 */
  29.  
  30. /* prototype definitions for functions */
  31. OSErr    GetVolStuff(short, short *, short *, StringPtr);
  32. Boolean    IsItCD(short, StringPtr);
  33. OSErr    StartAtTrack1(short);
  34. OSErr    AStatus(short, short *);
  35. void    pStrCpy(char *, char *);
  36. Boolean    pStrCmp(StringPtr, StringPtr);
  37.  
  38. /* **** WARNING:  DO NOT USE GLOBAL VARIABLES! **** */
  39.  
  40.  
  41. /************************************************************************
  42.  *
  43.  *  Function:        CDOpen
  44.  *
  45.  *  Purpose:        Open the driver and return the ioRefNum
  46.  *
  47.  *  Returns:        ioRefNum (used for subsequent calls to driver)
  48.  *
  49.  *  Side Effects:    none
  50.  *
  51.  *  Description:    We normally don't need any parameters.  If you have
  52.  *                    several CD SC drives attached, we will accept a 
  53.  *                    single parameter which is the SCSI ID of the drive.
  54.  *                    We cruise through the volume chain, trying to find
  55.  *                    an audio CD volume.  When we find it, we return both
  56.  *                    the vRefNum and dRefNum, concatenated together and
  57.  *                    converted into a string.
  58.  *
  59.  ************************************************************************/
  60. pascal void
  61. CDOpen(paramPtr)
  62. XCmdBlockPtr    paramPtr;
  63. {
  64.     Str31    returnString;
  65.     OSErr    result;
  66.     short    dRefNum;
  67.     short    vRefNum;
  68.     long    bothRefNums;
  69.     short    driveNumber;
  70.     short    status;
  71.     Str255    driverName;
  72.     Handle    playModeHandle;
  73.     
  74.     /* Must be no parameters or one parameters */
  75.     if ( paramPtr->paramCount > 1)
  76.     {
  77.         /* Report error in parameters by returning -1 */
  78.         NumToStr(paramPtr, (long) -1, returnString);
  79.         paramPtr->returnValue = PasToZero(paramPtr, (StringPtr) returnString);
  80.         return;
  81.     }
  82.     
  83.     if ( paramPtr->paramCount == 1)
  84.         driveNumber = atoi(*(paramPtr->params[0]));
  85.     else
  86.         driveNumber = -1;        /* -1 says "open first available" */
  87.     
  88.     GetIndString(driverName, STR_ID, DRIVER_STR);
  89.     if (driverName == nil)
  90.         result = ResError();
  91.     
  92.     result = GetVolStuff(driveNumber, &dRefNum, &vRefNum, driverName);
  93.     
  94.     if (result == noErr)
  95.     {
  96.         AStatus(dRefNum, &status);
  97.         if (status > 3)    /* not playing; seek to track 1 */
  98.             StartAtTrack1(dRefNum);
  99.     /* we must ignore any possible error coming back from StartAtTrack1(),
  100.     ** because the first track might be data, and this will give us a paramErr.
  101.     */
  102.     }
  103.  
  104.     /* Concatentate vRefNum & dRefNum, convert to string & return it */
  105.     if (result == noErr)
  106.         bothRefNums = (long)vRefNum << 16 | ((long)dRefNum & 0x0000FFFF);
  107.     else
  108.         bothRefNums = 0;
  109.     
  110.     NumToStr(paramPtr, (long) bothRefNums, returnString);
  111.     paramPtr->returnValue = PasToZero(paramPtr, (StringPtr) returnString);
  112.     
  113.     SetGlobal(paramPtr, GLOBALNAME, paramPtr->returnValue);
  114.     playModeHandle = PasToZero(paramPtr, "\p9");
  115.     SetGlobal(paramPtr, PLAYMODE, playModeHandle);
  116.     DisposHandle(playModeHandle);
  117. }
  118.  
  119.  
  120. /************************************************************************
  121.  *
  122.  *  Function:        GetVolStuff
  123.  *
  124.  *  Purpose:        get volume reference number for audio CD
  125.  *
  126.  *  Returns:        OSErr
  127.  *                    noErr if we found an audio volume
  128.  *                    nsvErr if no such volume was mounted
  129.  *                    (may return other errors if problem with system)
  130.  *
  131.  *  Side Effects:    fills in vRefNum
  132.  *
  133.  *  Description:    using the PBHGetVInfo call documented on pages IV-129
  134.  *                    and IV-130 of IM v4, we loop through the list of
  135.  *                    mounted volumes.  For each volume that we find, check
  136.  *                    to see if it's a CD (using IsItCD).  If it is a CD,
  137.  *                    check and see if it's the SCSI ID.  If it
  138.  *                    is the right SCSI ID, return the vRefNum and dRefNum
  139.  *                    that is associated with that volume.
  140.  *                    If we are passed a SCSI ID of -1, it means "open the
  141.  *                    first CD we find."
  142.  *
  143.  ************************************************************************/
  144. OSErr
  145. GetVolStuff(scsiID, dRefNum, vRefNum, driverName)
  146. short    scsiID;            /* which CD drive to find */
  147. short    *dRefNum;        /* driver reference number */
  148. short    *vRefNum;        /* volume reference number */
  149. StringPtr    driverName;    /* name of the driver we're comparing against */
  150. {
  151.     short    i;
  152.     OSErr    result;
  153.     Boolean    foundIt;
  154.     short    currentScsiID;
  155.     HVolumeParam    hParamBlock;
  156.     
  157.     result = noErr;
  158.     foundIt = false;
  159.     
  160.     for (i = 1; result != nsvErr && foundIt == false; i++)
  161.     {
  162.         hParamBlock.ioCompletion = 0;
  163.         hParamBlock.ioNamePtr = nil;
  164.         hParamBlock.ioVRefNum = 0;
  165.         hParamBlock.ioVolIndex = i;
  166.         result = PBHGetVInfo(&hParamBlock,false);
  167.         if (IsItCD(hParamBlock.ioVDRefNum, driverName) == true)
  168.         {
  169.             if (scsiID == -1)
  170.                 foundIt = true;    /* find anything if asked for -1 */
  171.             else
  172.             {
  173.                 currentScsiID = (-hParamBlock.ioVDRefNum) - 32 -1;
  174.                 if (currentScsiID == scsiID)
  175.                     foundIt = true;
  176.             }
  177.         }
  178.     }
  179.     if (result == noErr)
  180.     {
  181.         *dRefNum = hParamBlock.ioVDRefNum;
  182.         *vRefNum = hParamBlock.ioVRefNum;
  183.     }
  184.  
  185.     return result;
  186. }
  187.  
  188. /************************************************************************
  189.  *
  190.  *  Function:        IsItCD
  191.  *
  192.  *  Purpose:        determine if this driver reference number points to
  193.  *                    a CD or not.
  194.  *
  195.  *  Returns:        Boolean
  196.  *                    true = this dRefNum points to a CD
  197.  *                    false = this dRefNum points to something else
  198.  *
  199.  *  Side Effects:    none
  200.  *
  201.  *  Description:    The unit table points to the device control entry.
  202.  *                    The device control entry contains either a pointer
  203.  *                    to a ROM based driver or a handle
  204.  *                    to a RAM based driver.  The driver has the
  205.  *                    name starting at byte offset 18.  All this stuff
  206.  *                    is documented in Inside Mac, II-187 through II-192
  207.  *                    and IV-215
  208.  *
  209.  *                    Note that the Apple CD-ROM driver claims to be ROM
  210.  *                    based(!), but third party drivers such as OMI's
  211.  *                    correctly claim to be RAM based.
  212.  *
  213.  *                    Check out the driver name and see if it matches the
  214.  *                    driver name we're passed.  If it does, this is a CD.
  215.  *
  216.  ************************************************************************/
  217. Boolean
  218. IsItCD(dRefNum, driverName)
  219. short        dRefNum;
  220. StringPtr    driverName;
  221. {
  222.     Boolean        result;
  223.     DCtlHandle    dCtlHandle;
  224.     StringPtr    driverNamePtr;
  225.     Handle        driverHandle;
  226.     
  227.     result = false;                /* assume not a CD */
  228.  
  229.     dCtlHandle = GetDCtlEntry(dRefNum);
  230.     
  231.     if ((**dCtlHandle).dCtlFlags & dRAMBased)
  232.     {
  233.         driverHandle = (Handle) (**dCtlHandle).dCtlDriver;
  234.         driverNamePtr = (char *) *driverHandle+18;  /* magic number! */
  235.     }
  236.     else
  237.         driverNamePtr = (char *) (**dCtlHandle).dCtlDriver+18;  /* magic number! */
  238.                     /* offset of driver name in device control entry. */
  239.     
  240.     if (pStrCmp(driverNamePtr, driverName))
  241.         result = true;        /* this is a CD */
  242.     return result;
  243. }
  244.  
  245.  
  246. /************************************************************************
  247.  *
  248.  *  Function:        StartAtTrack1
  249.  *
  250.  *  Purpose:        start Searching an audio track
  251.  *
  252.  *  Returns:        OSErr.  Probably either
  253.  *                        noErr        everything's hunky-dory!
  254.  *                        paramErr    you messed up the call somehow.
  255.  *
  256.  *  Side Effects:    starts search.
  257.  *
  258.  *  Description:    The track that you pass in is the location to which
  259.  *                    you want to search.  You can then start play with
  260.  *                    a pause command.
  261.  *
  262.  ************************************************************************/
  263. OSErr
  264. StartAtTrack1(refNum)
  265. short    refNum;
  266. {
  267.     CDParam    myPB;
  268.     
  269.     myPB.ioCompletion = 0;
  270.     myPB.ioNamePtr = (char *) 0;
  271.     myPB.ioVRefNum = 1;
  272.     myPB.ioCRefNum = refNum;
  273.     myPB.csCode = ASEARCH;
  274.     
  275.     myPB.csParam[0] = 0;
  276.     myPB.csParam[1] = TRACKADDR;
  277.     myPB.csParam[2] = 0;
  278.     myPB.csParam[3] = 0;
  279.     myPB.csParam[4] = 0;
  280.     myPB.csParam[5] = 1;        /* search to track 1 */
  281.     myPB.csParam[6] = 0;
  282.     myPB.csParam[7] = 0;        /* search and pause */
  283.     myPB.csParam[8] = 0;
  284.     myPB.csParam[9] = STEREO;
  285.     return (PBControl(&myPB, false));
  286. }
  287.  
  288. /************************************************************************
  289.  *
  290.  *  Function:        AStatus
  291.  *
  292.  *  Purpose:        return CD audio status
  293.  *
  294.  *  Returns:        OSErr.  Probably either
  295.  *                        noErr        everything's hunky-dory!
  296.  *                        paramErr    you messed up the call somehow.
  297.  *
  298.  *  Side Effects:    modifies "status" to reflect the audio status byte
  299.  *                    returned by the driver.
  300.  *
  301.  *  Description:    Simply call the driver and return the audio status
  302.  *                    byte that the driver gives us.
  303.  *
  304.  ************************************************************************/
  305. OSErr
  306. AStatus(refNum, status)
  307. short    refNum;
  308. short    *status;
  309. {
  310.     CDStatusParam    myPB;
  311.     OSErr    result;
  312.     
  313.     myPB.ioCompletion = 0;
  314.     myPB.ioNamePtr = (char *) 0;
  315.     myPB.ioVRefNum = 1;
  316.     myPB.ioCRefNum = refNum;
  317.     myPB.csCode = ASTATUS;
  318.     
  319.     result = PBControl(&myPB, false);
  320.     *status = (short) myPB.audioStatus;
  321.     return result;
  322. }
  323.  
  324.  
  325.  
  326. /************************************************************************
  327.  *
  328.  *  Function:    pStrCpy
  329.  *
  330.  *  Purpose:    copy a pascal string.
  331.  *
  332.  *  Returns:        nothing
  333.  *
  334.  *  Side Effects:    'dest' contents are changed.
  335.  *
  336.  *  Description:
  337.  *
  338.  *
  339.  ************************************************************************/
  340. void
  341. pStrCpy(src, dest)
  342. char *src;
  343. char *dest;
  344. {
  345.     short    i;
  346.     short    length;
  347.     
  348.     length = src[0];
  349.     
  350.     for (i = 0; i <= length; i++)
  351.         dest[i] = src[i];
  352. }
  353.  
  354.  
  355. /************************************************************************
  356.  *
  357.  *  Function:    pStrCmp
  358.  *
  359.  *  Purpose:    compare 2 pascal string.
  360.  *
  361.  *  Returns:        true if equal, false if not
  362.  *
  363.  *  Side Effects:    none
  364.  *
  365.  *  Description:
  366.  *
  367.  *
  368.  ************************************************************************/
  369. Boolean
  370. pStrCmp(src, dest)
  371. StringPtr    src;
  372. StringPtr    dest;
  373. {
  374.     short    length;
  375.     
  376.     length = src[0];
  377.     
  378.     while (length--)
  379.         if (*src++ != *dest++)
  380.             return false;
  381.     return true;
  382. }
  383.  
  384. #include <XCmdGlue.inc.c>
  385.